#include "utils.h"
#include <assert.h>

// 把字节流转化成对应的十六进制数字符串
std::string hex2string(const char* hexdata, size_t len) {
    std::string result;
    for (size_t i = 0; i < len; i++) {
        static const char dec2hex[16+1] = "0123456789abcdef";
        result += dec2hex[(hexdata[i] >> 4) & 15];
        result += dec2hex[ hexdata[i]       & 15];
    }
    return result;
}

int char2num(char c) {
    if (c >= '0' && c <= '9') {
        return c - '0';
    } else if (c >= 'a' && c <= 'z') {
        return c - 'a' + 10;
    } else if (c >= 'A' && c <= 'Z') {
        return c - 'A' + 10;
    } else {
        assert(0);
        return 0;
    }
}

// 将十六进制数的字符串转化为对应的字节数组
void string2hex(std::string str, char* hexdata, size_t len) {
    size_t strlen = str.size();
    assert((strlen >> 1) <= len);
    if (strlen & 1) str = '0' + str;
    for (size_t i = 0; i < len; i += 2) {
        int curr = char2num(str[i]) << 4;
        curr += char2num(str[i + 1]);
        hexdata[i >> 1] = char(curr);
    }
}

// 对字节数组使用的 PRF 仿函数
void PRF::operator()(const void *data, size_t dataLen, char* result) {
    hashFunc(data, dataLen);
    unsigned char hashdata[32];
    bzero(hashdata, 32);
    hashFunc.getHash(hashdata);
    hashFunc.reset();
    zuc.Initialization(key, hashdata);
    zuc.GenerateKeyStream((unsigned int*)result, (resultLength >> 2) + 1);
}

// 对 string 使用的 PRF 仿函数
std::string PRF::operator()(std::string text) {
    hashFunc(text);
    unsigned char hashdata[32];
    bzero(hashdata, 32);
    hashFunc.getHash(hashdata);
    hashFunc.reset();
    char *buffer = new char[resultLength];
    zuc.Initialization(key, hashdata);
    zuc.GenerateKeyStream((unsigned int*)buffer, (resultLength >> 2) + 1);
    std::string result = hex2string(buffer, resultLength);
    delete[] buffer;
    return result;
}

// 返回的是十六进制字符串
std::string F(std::string key, std::string m) {
    using std::string;
    mpz_class k(key, 16);
    PRF& prf = Singleton<PRF>::Instance();
    prf.setup(k, 128);
    return prf(m);
}

std::string Fp(std::string key, std::string m) {
    return F(key, m);
}

// 返回的是十六进制字符串
std::string H(std::string text) {
    SHA256 hashFunc;
    return hashFunc(text);
}

// 对称加密算法 Enc
std::string Enc(mpz_class key, std::string str) {
    str = "11" + str;
    int len = str.size();
    std::string str2hex = hex2string(str.c_str(), len);
    SHA256 hashFunc;
    hashFunc(key.get_str(16));
    unsigned char hashdata[32];
    bzero(hashdata, 32);
    hashFunc.getHash(hashdata);
    ZUC zuc(hashdata, hashdata + 16);
    char* keyBytes = new char[len + 4];
    zuc.GenerateKeyStream((unsigned int*)keyBytes, (len >> 2) + 1);
    mpz_class m_data(str2hex, 16);
    mpz_class key_data(hex2string(keyBytes, len), 16);
    m_data = m_data ^ key_data;
    delete[] keyBytes;
    return m_data.get_str(16);
}

// 对称加密算法 Dec
std::string Dec(mpz_class key, std::string str) {
    int len = str.size();
    SHA256 hashFunc;
    hashFunc(key.get_str(16));
    unsigned char hashdata[32];
    bzero(hashdata, 32);
    hashFunc.getHash(hashdata);
    ZUC zuc(hashdata, hashdata + 16);
    char* keyBytes = new char[len + 4];
    zuc.GenerateKeyStream((unsigned int*)keyBytes, (len >> 2) + 1);
    mpz_class c_data(str, 16);
    mpz_class key_data(hex2string(keyBytes, len >> 1), 16);
    c_data = c_data ^ key_data;
    char* t = new char[len];
    string2hex(c_data.get_str(16), t, len);
    std::string result(t);
    delete[] t;
    if (result[0] == '1' && result[1] == '1') {
        return result.substr(2);
    } else {
        return std::string("0");
    }
}


